package com.spring.housing1.other;

import com.spring.housing1.constant.isNull;
import com.spring.housing1.returnType.CommenResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class AopIntercepters {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Qualifier("Db1Template")
    @Autowired
    JdbcTemplate jdbcTemplate;

    @Pointcut("@annotation(com.spring.housing1.constant.ServiceTokenRequired)")
    public void validateToken(){}
    @Pointcut("@annotation(com.spring.housing1.constant.isNull)")
    public void validNull(){}



    /**
     * 空值校验(必传值校验) get(map对象)/post(实体类)请求  参数为map或LinkedHashMap
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     * @author: zhou
     */
    @Around("validNull()&&@annotation(is)")
    public Object validNull(ProceedingJoinPoint proceedingJoinPoint, isNull is) throws Throwable {
        String[] keys = is.value();
        String[] reqire_param = Arrays.copyOf(keys,keys.length);
        Object[] args = proceedingJoinPoint.getArgs();
        int flag =0;
        int res_flag = keys.length;
//        请求方式判断
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String method = request.getMethod();
//        把请求头里的参数加进去
        String open_id = request.getHeader("open_id");


//        判断请求参数中是否包含必传参数(在方法上有@isNull注解)
//        get请求参数在请求param中
        if(method.toLowerCase().equals("get")) {
            for (Object obj : args) {
//            判断是否为json字符
                if (obj.getClass().getName().contains("Map") || obj.getClass().getName().contains("Map".toLowerCase())) {
                    log.info(obj.getClass().getName());
                    Map m = (Map<String, String>) obj;
                    for (int i = 0; i < keys.length; i++) {
//                    判断是否有该key
                        if (m.containsKey(keys[i])) {
//                        判断当前参数key值是否为空!
                            reqire_param[i] = "";
                            flag++;
//                            请求头和请求参数都没有会被拦截
                            if (m.get(keys[i]) == null ) {
                                throw new NullPointerException(keys[i] + "值不能为空");
                            }
                        }
                    }
                } else {
                    throw new RuntimeException("传入参数类型错误!");
                }
            }
        }
//        post请求
        else{
            Object[] argss = proceedingJoinPoint.getArgs();
            String params = "";
            //获取请求参数集合并进行遍历拼接
            if(argss.length>0){
                Object object = args[0];
//                    将参数转为map对象
                Map map = getKeyAndValue(object);
                for (int i = 0; i < keys.length; i++) {
//                    判断是否有该key
                    if (map.containsKey(keys[i])) {
//                        判断当前参数key值是否为空!
                        reqire_param[i] = "";
                        flag++;
                        if (map.get(keys[i]) == null) {
                            throw new NullPointerException(keys[i] + "值不能为空或参数不存在!");
                        }
                    }
                }

            }
        }

        if(flag ==res_flag){
            return  proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
        }
        else {
            return  new CommenResult<>(401,"缺少必传参数!","");
        }


    }


    public static Map<String, Object> getKeyAndValue(Object obj) {
        Map<String, Object> map = new HashMap<>();
        // 得到类对象
        Class userCla = (Class) obj.getClass();
        /* 得到类中的所有属性集合 */
        Field[] fs = userCla.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];
            f.setAccessible(true); // 设置些属性是可以访问的
            Object val = new Object();
            try {
                val = f.get(obj);
                // 得到此属性的值
                map.put(f.getName(), val);// 设置键值
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        }
        return map;
    }

    /**
     * 验证token
     * @param joinPoint
     * @return
     * @throws Throwable
     * @author: zhou
     */
    @Around("validateToken()")
        public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String token = request.getParameter("open_id");
        String head = request.getHeader("open_id");
        String token2 = request.getParameter("session_value");
        String head2 = request.getHeader("session_value");
        log.info(token+"_"+head+"_"+token2+"_"+head2);
        String current_token_key = (token == null ? head : token);
        String current_token_value = (token2 == null ? head2 : token2);
//        token不为空且在请求头中或者请求体中时通过验证
        if (current_token_key ==null || current_token_value ==null) {
            return  new CommenResult<>(401,"session_value或open_id为空 返回结果异常","");
        } else {
            log.info("当前open_id为:{}",current_token_key);
            log.info("当前session_value为:{}",current_token_value);
////         判断当前是否为同一客户端打开
            Map<String, Object> count = jdbcTemplate.queryForMap("select count(*) from  login_wx where open_id = ?", current_token_key);
            if(Integer.parseInt(count.get("count(*)").toString())>0){
                Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap("select open_id,session_value from  login_wx where open_id = ?", current_token_key);
                log.info("通过session_key获取的session_value为:"+stringObjectMap.get("session_value"));
                if (stringObjectMap.get("session_value") != null) {//判断是否登陆过
                    if (stringObjectMap.get("session_value").equals(current_token_value)) {//token验证通过
                        log.info("通过open_id获取的session_value为:"+stringObjectMap.get("session_value"));
                        return   joinPoint.proceed(joinPoint.getArgs());
                    } else {
                        return  new CommenResult<>(401,"token失效请重新登录","");
                    }
                }else{
                    return  new CommenResult<>(401,"token失效请重新登录2","");
                }
            }
           else{
                return  new CommenResult<>(401,"登录异常!","");

            }
//            判断session是否过期，且快接近过期延长过期时间
        }


    }
}
